package hdgeom;

import hdgeom.primitives.AbstractShape;
import hdgeom.primitives.Polygon2D;

import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Vector;

import processing.core.PGraphics;
import processing.core.PVector;

public class EdgeList extends AbstractShape{

		private Vector<PVector> pts=new  Vector<PVector>();
		boolean checked;

	
		

		

		
		/*
		 * public PVector getPosByDistance(float d){ float travelDist=0; float
		 * travelDistNext=0; int i=0; int iNext=0; while(travelDistNext<d){ i=iNext;
		 * iNext=i+1; travelDist=travelDistNext;
		 * travelDistNext=travelDist+PVector.dist(get(i),get(iNext)); } return
		 * Vec2D.getFromAtoBAbsolute(get(i), get(iNext), d-travelDist); } public
		 * Vector<PVector> getSegmentsByDistance(float d1,float d2){ Vector<PVector>
		 * list=new Vector<PVector>(); float travelDist=0; float travelDistNext=0;
		 * int i=0; int iNext=0; while(travelDistNext<d1){ i=iNext; iNext=i+1;
		 * travelDist=travelDistNext;
		 * travelDistNext=travelDist+PVector.dist(get(i),get(iNext)); }
		 * list.add(Vec2D.getFromAtoBAbsolute(get(i), get(iNext), d1-travelDist));
		 * travelDistNext=travelDist; iNext=i; while(travelDistNext<d2){ i=iNext;
		 * iNext=i+1; travelDist=travelDistNext;
		 * travelDistNext=travelDist+PVector.dist(get(i),get(iNext)); if
		 * (travelDistNext<d2){ list.add(new PVector(get(iNext))); } }
		 * list.add(Vec2D.getFromAtoBAbsolute(get(i), get(iNext), d2-travelDist));
		 * return list; }
		 */
		public int getPointByLength(float l, float[] result) {
			int i = 0;
			int j = 0;
			float d1 = 0;
			float d2 = 0;

			while (d2 < l) {
				j = (i + 1) % getNumVertices();
				d1 = d2;
				d2 += distance(getX(i), getY(i), getX(j), getY(j));
				i+=2;
				i = i % getNumVertices();

			}
			float restL = l - d1;
			i = i - 2;
			if (i < 0)
				i = getNumVertices() - 2;
			float vX = getX(j) - getX(i);
			float vY = getY(j) - getY(i);
			float d = d2 - d1;

			if (d > 0) {
				vX = vX * restL / d;
				vY = vY * restL / d;
			}
			result[0] = getX(i) + vX;
			result[1] = getY(i) + vY;
			
			return i;
		}


		public PVector get(int i) {
			return pts.get(i % this.pts.size());
		}

		public void reverse() {
			Collections.reverse(pts);
		}

		public Vector<PVector> getPts() {
			return pts;
		}
		
		public float getPerimeter(){
			float per=0;
			for (int i=0;i<pts.size()-1;i+=2){
				PVector v1=pts.get(i);
				PVector v2=pts.get(i+1);
				per+=v1.dist(v2);
			}
			
			return per;
		}

		public void addEdge(PVector p1,PVector p2) {
			pts.add(p1);
			pts.add(p2);
		}
		public void addEdge(float x1,float y1,float x2,float y2) {
			pts.add(new PVector(x1,y1));
			pts.add(new PVector(x2,y2));
		}
		

		public void setPts(Vector<? extends PVector> pts) {
			this.pts = (Vector<PVector>) pts;
		}

		public static ArrayList<Polygon2D> getRings(Area area) {
			PathIterator pi = area.getPathIterator(null);
			ArrayList<Polygon2D> allPoints = new ArrayList<Polygon2D>();
			Polygon2D points = new Polygon2D();
			while (pi.isDone() == false) {
				double[] coordinates = new double[6];
				int type = pi.currentSegment(coordinates);
				switch (type) {
				case PathIterator.SEG_MOVETO:
					points = new Polygon2D();
					points.addPt(new PVector((float) coordinates[0],
							(float) coordinates[1]));
					break;
				case PathIterator.SEG_LINETO:
					PVector newP = new PVector((float) coordinates[0],
							(float) coordinates[1]);
					if (!points.get(0).equals(newP)) {
						points.addPt(newP);
					}
					break;
				case PathIterator.SEG_CLOSE:
					allPoints.add(points);
					break;
				default:
					break;
				}
				pi.next();
			}
			return allPoints;
		}

		/*
		 * public ArrayList<Edge2D>splitPts(float x1,float y1,float x2,float y2){
		 * Vector<PVector>newPts=new Vector<PVector>();
		 * Vector<PVector>intersectPts=new Vector<PVector>(); for (int
		 * i=0;i<this.pts.size();i++){ PVector p1=this.get(i); PVector
		 * p2=this.get((i+1)%pts.size()); Vec2D v = segmentSegmentIntersection(x1,
		 * y1, x2, y2, p1.getX(), p1.getY(), p2.getX(), p2.getY()); newPts.add(p1);
		 * if (v!=null){ newPts.add(v); intersectPts.add(v); } } pts=newPts;
		 * PVectorDistanceComparator hP = new PVectorDistanceComparator( new
		 * Vec2D(x1, y1)); Collections.sort(intersectPts, hP);
		 * ArrayList<Edge2D>newEdges=new ArrayList<Edge2D>(); for (int
		 * i=0;i<intersectPts.size()-1;i++){ PVector p1=intersectPts.get(i); PVector
		 * p2=intersectPts.get((i+1)%pts.size()); Edge2D edge=new Edge2D(p1,p2);
		 * newEdges.add(edge); } return newEdges; } public PVector[]
		 * splitConvexWithLine(float x1,float y1,float x2,float y2){ PVector[]
		 * splitpts=new PVector[2]; for (int i=0;i<this.pts.size();i++){ PVector
		 * p1=this.get(i); PVector p2=this.get((i+1)%pts.size()); Vec2D v =
		 * Vec2D.segmentLineIntersection(x1, y1, x2, y2, p1.x, p1.y, p2.x, p2.y);
		 * 
		 * if (v!=null){ if (splitpts[0]==null){ splitpts[0]=v; }else{
		 * splitpts[1]=v; } } } PVector p1=new PVector(x1,y1); if
		 * (p1.dist(splitpts[0])>p1.dist(splitpts[1])){ PVector temp=splitpts[0];
		 * splitpts[0]=splitpts[1]; splitpts[1]=temp; } return splitpts; } public
		 * ArrayList<Polygon2D>split(float x1,float y1,float x2,float y2){ HEFace
		 * face=null; ArrayList<HENode>nodes=new ArrayList<HENode>(); for (int
		 * i=0;i<pts.size();i++){ PVector p=pts.get(i); nodes.add(new HENode(p)); }
		 * Vector<HEdge> edges=getHEdges();
		 * 
		 * ArrayList<HENode> intersectPts = new ArrayList<HENode>();
		 * ArrayList<HEdge> intersectEdges = new ArrayList<HEdge>(); Vector<HEdge>
		 * newEdges = new Vector<HEdge>();
		 * 
		 * for (int i = 0; i < edges.size(); i++) { HEdge e = edges.get(i);
		 * 
		 * Vec2D v = segmentSegmentIntersection(x1, y1, x2, y2, e.x1(), e.y1(),
		 * e.x2(), e.y2()); if (v == null) {
		 * 
		 * newEdges.add(e); } else { HENode n = new HENode(v.getX(), v.getY());
		 * nodes.add(n); intersectPts.add(n); intersectEdges.add(e); } }
		 * 
		 * System.out.println("split: " + intersectPts.size()); for (int i = 0; i <
		 * intersectPts.size(); i++) { HENode n = intersectPts.get(i); HEdge e =
		 * intersectEdges.get(i); HENode n1 = e.getOrg(); HENode n2 = e.getDest();
		 * e.detach(); HEdge newE1 = new HEdge(n1, n); newE1.attach();
		 * newEdges.add(newE1); HEdge newE2 = new HEdge(n, n2); newE2.attach();
		 * newEdges.add(newE2); } PVectorDistanceComparator hP = new
		 * PVectorDistanceComparator( new Vec2D(x1, y1));
		 * Collections.sort(intersectPts, hP); for (int i = 0; i <
		 * intersectPts.size() - 1; i += 2) { HENode n1 = intersectPts.get(i);
		 * HENode n2 = intersectPts.get(i + 1); HEdge newEdge = new HEdge(n1, n2);
		 * newEdge.attach(); newEdges.add(newEdge); } edges = newEdges;
		 * ArrayList<Polygon2D>newPolygons=new ArrayList<Polygon2D>();
		 * ArrayList<HEFace> newFaces=createRings(edges, 1);
		 * System.out.println("newFaces: "+newFaces.size()); for (int
		 * i=0;i<newFaces.size();i++){ HEFace cFace=newFaces.get(i);
		 * Vector<HENode>cNodes=cFace.getFaceNodes(); Polygon2D p=new
		 * Polygon2D(cNodes); newPolygons.add(p); } return newPolygons; }
		 */

		public boolean isChecked() {
			return checked;
		}

		public void setChecked(boolean checked) {
			this.checked = checked;
		}

		/*
		 * public int getClosestSegment(float x,float y){ return
		 * getClosestSegment(x,y,pts); }
		 * 
		 * public static int getClosestSegment(float x,float y,Vector<? extends
		 * PVector>pts){ int cI=-1; float minD=Float.MAX_VALUE; for (int
		 * i=0;i<pts.size();i++){ PVector p1=pts.get(i); PVector
		 * p2=pts.get((i+1)%pts.size()); float cD=Vec2D.getDistToSeg(p1.getX(),
		 * p1.getY(), p2.getX(), p2.getY(), x, y);
		 * 
		 * if (cD<minD){ cI=i; minD=cD;
		 * 
		 * } } return cI; }
		 * 
		 * public float getClosestDistSqDist(float x,float y){ PVector
		 * closestP=null; double minD=Double.MAX_VALUE; float length=0; float
		 * currentLength=0; PVector lastPos=pts.get(0); for (int
		 * i=0;i<pts.size();i++){ PVector p1=pts.get(i); length+=Vec2D.dist(p1,
		 * lastPos); lastPos=p1; PVector p2=pts.get((i+1)%pts.size()); double
		 * cD=Line2D.ptSegDistSq(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y);
		 * if (cD<minD){ minD=cD; PVector point=Vec2D.getClosestPointToSeg(new
		 * Vec2D(x,y), p1, p2); currentLength=Vec2D.dist(p1, point)+length; } }
		 * return currentLength; }
		 */

		public PVector getVertex(int i) {
			return pts.get(i);
		}
		

		public float getX(int i) {
			// TODO Auto-generated method stub
			return pts.get(i).x;
		}

		
		public float getY(int i) {
			// TODO Auto-generated method stub
			return pts.get(i).y;
		}

		
		public void setPosition(int i, float x, float y) {
			PVector p = get(i);
			p.x = x;
			p.y = y;
		}

		@Override
		public int getNumVertices() {
			// TODO Auto-generated method stub
			return pts.size();
		}

		@Override
		public void getPosition(int i, float[] coords) {
			// TODO Auto-generated method stub
			PVector p = get(i);
			coords[0] = p.x;
			coords[1] = p.y;
			coords[2] = p.z;
		}

		@Override
		public void setPosition(int i, float x, float y, float z) {
			// TODO Auto-generated method stub
			PVector p = get(i);
			p.x = x;
			p.y = y;
			p.z = y;
		}

		

		@Override
		public void display2D(PGraphics g) {
			// TODO Auto-generated method stub
			for (int i=0;i<pts.size()-1;i+=2){
				PVector v1=pts.get(i);
				PVector v2=pts.get(i+1);
				g.line(v1.x,v1.y,v2.x,v2.y);
				
			}
		}

		@Override
		public void display3D(PGraphics g) {
			// TODO Auto-generated method stub
			for (int i=0;i<pts.size()-1;i+=2){
				PVector v1=pts.get(i);
				PVector v2=pts.get(i+1);
				g.line(v1.x,v1.y,v1.z,v2.x,v2.y,v2.z);
			}
		}
	
}
